package com.un.ebs.customer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.enums.SexEnum;
import com.un.ebs.core.exception.BusinessEntityNotFoundException;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.util.OSSUtil;
import com.un.ebs.core.util.SecurityUtils;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.customer.domain.*;
import com.un.ebs.customer.dto.DefunctAddDto;
import com.un.ebs.customer.dto.DefunctAttrDto;
import com.un.ebs.customer.dto.DefunctUpdateDto;
import com.un.ebs.customer.dto.DefunctVo;
import com.un.ebs.customer.mapper.*;
import com.un.ebs.customer.service.CustomerService;
import com.un.ebs.customer.service.DefunctService;
import com.un.ebs.sys.domain.User;
import com.un.ebs.sys.service.AppTenantService;
import com.un.ebs.sys.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liubo
 * @since 2019-09-24
 */
@Service
public class DefunctServiceImpl extends ServiceImpl<DefunctMapper, Defunct> implements DefunctService {

    @Resource
    private AppTenantService appTenantService;

    @Resource
    private UserService userService;

    @Resource
    private CustomerMapper customerMapper;

    @Resource
    private CustomerDefunctMapper customerDefunctMapper;

    @Resource
    private CustomerAndDefunctExtMapper customerAndDefunctExtMapper;

    @Resource
    private DefunctExtMapper defunctExtMapper;

    @Resource
    private OrderAttrExtMapper orderAttrExtMapper;

    @Resource
    private CustomerService customerService;

    @Override
    public String add(DefunctAddDto req) {
        DefunctUpdateDto obj = new DefunctUpdateDto();
        BeanUtils.copyProperties(req, obj);
        return save(obj);
    }

    @Override
    public String add(String name, String tombSKuId) {
        DefunctUpdateDto obj = new DefunctUpdateDto();
        obj.setName(name);
        obj.setTombSkuId(tombSKuId);
        return save(obj);
    }

    @Override
    public void update(DefunctUpdateDto req) {
        save(req);
    }

    private String save(DefunctUpdateDto req) {
        Defunct obj;
        if (StringUtils.isNullOrEmpty(req.getId())) {
            obj = new Defunct();
        } else {
            obj = getById(req.getId());
        }
        obj.setName(req.getName());
        obj.setSex(req.getSex());
        obj.setBirthday(req.getBirthday());
        obj.setDefunctDate(req.getDefunctDate());
        obj.setIdNumber(req.getIdNumber());
        obj.setAreaId(req.getAreaId());
        obj.setAddress(req.getAddress());
        obj.setDefunctTypeDict(req.getDefunctTypeDict());
        obj.setDefunctAddDict(req.getDefunctAddDict());
        obj.setDefunctIdNumber(req.getDefunctIdNumber());
        obj.insertOrUpdate();
        return obj.getId();
    }

    @Override
    public String nameExist(String name, String custId) {
        LambdaQueryWrapper<CustomerAndDefunctExt> lq = Wrappers.lambdaQuery();
        lq.eq(CustomerAndDefunctExt::getDefunctName, name);
        lq.eq(CustomerAndDefunctExt::getCustomerId, custId);
        lq.eq(CustomerAndDefunctExt::getIsDelete, false);
        lq.eq(CustomerAndDefunctExt::getCustomerDeleteStatus, false);
        if (customerAndDefunctExtMapper.selectCount(lq) > 0) {
            return customerAndDefunctExtMapper.selectList(lq).stream().findFirst().get().getDefunctId();
        } else {
            return null;
        }
    }

    @Override
    public void buryBook(String id, Date time) {
        Defunct obj = getById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "使用者");
        }

        if (obj.getIsBury()) {
            throw new BusinessException("墓位使用者已安葬。");
        }

        if (time.before(new Date())) {
            throw new BusinessException("预约时间不能是已经过去的时间。");
        }

        obj.setTombBuryTime(time);
        obj.updateById();
    }

    @Override
    public void buryComplete(String id, Date time) {
        Defunct obj = getById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "墓位使用者");
        }

        if (time == null) {
            obj.setTombBuryTime(new Date());
        } else {
            obj.setTombBuryTime(time);
        }

        obj.setIsBury(true);
        obj.updateById();

    }

    @Override
    public void buryCancel(String id) {
        Defunct obj = getById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "墓位使用者");
        }

        obj.setIsBury(false);
        obj.updateById();
    }

    @Override
    public Defunct queryById(String id) {
        return getBaseMapper().selectById(id);
    }

    @Override
    public List<DefunctAttrDto> queryAttrs(String id) {
        LambdaQueryWrapper<OrderAttrExt> lq = Wrappers.lambdaQuery();
        lq.eq(OrderAttrExt::getDefunctId, id);
        lq.eq(OrderAttrExt::getSubmitStatus, true);
        lq.eq(OrderAttrExt::getCancelStatus, false);
        return orderAttrExtMapper.selectList(lq).stream().map(s -> {
            DefunctAttrDto obj = new DefunctAttrDto();
            obj.setAttrId(s.getAttrId());
            obj.setAttrName(s.getAttrName());
            obj.setGroupName(s.getGroupName());
            obj.setFileUrl(OSSUtil.getObjectUrl(s.getFileUrl()).toString());
            obj.setOrderCode(s.getCode());
            obj.setSubmitTime(s.getSubmitTime());
            return obj;
        }).collect(Collectors.toList());
    }

    @Override
    public DefunctVo queryViewById(String id) {
        DefunctExt ext = defunctExtMapper.selectById(id);
        DefunctVo ret = new DefunctVo();
        BeanUtils.copyProperties(ext, ret);
        ret.setAttrs(queryAttrs(id));
        return ret;
    }

    @Override
    public void delete(String id) {
        getBaseMapper().deleteById(id);
    }

    @Override
    public IPage<DefunctExt> query(String searchText, Boolean isBury, int pageIndex, int pageSize) {
        Page<DefunctExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<DefunctExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(DefunctExt::getName, searchText).or().
                    like(DefunctExt::getTombSkuNameAs, searchText);
        }
        if (!customerService.hasQueryAllPower()) {
            List<String> ids = queryDefunctIdByUserId(SecurityUtils.getUserContent().getId());
            lq.in(DefunctExt::getId, ids);
        }
        if (isBury != null) {
            lq.eq(DefunctExt::getIsBury, isBury);
        }
        lq.eq(DefunctExt::getIsDelete, false);
        return defunctExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<DefunctExt> queryByCustomer(String searchText, int pageIndex, int pageSize) {
        Page<DefunctExt> page = new Page<>(pageIndex, pageSize);
        List<String> ids = new ArrayList<>();
        LambdaQueryWrapper<DefunctExt> query = Wrappers.lambdaQuery();
        LambdaQueryWrapper<CustomerAndDefunctExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            query.like(DefunctExt::getName, searchText).or().
                    like(DefunctExt::getTombSkuNameAs, searchText);
        }

        if (customerService.hasQueryAllPower()) {
            return defunctExtMapper.selectPage(page, query);
        } else {
            ids = customerAndDefunctExtMapper.selectList(lq).stream().map(s -> s.getDefunctId()).distinct().collect(Collectors.toList());
            lq.eq(CustomerAndDefunctExt::getPersonnelId, SecurityUtils.getUserContent().getPersonnelId());

            if (!StringUtils.isNullOrEmpty(ids)) {
                query.in(DefunctExt::getId, ids);
            } else {
                query.isNull(DefunctExt::getId);
            }
            query.or().eq(DefunctExt::getCreateAt, SecurityUtils.getUserContent().getId());
        }
        query.eq(DefunctExt::getIsDelete, false);

        return defunctExtMapper.selectPage(page, query);
    }

    @Override
    public List<DefunctExt> queryAnniversaries() {
        return baseMapper.selectByAnniversaries(2);
    }

    @Transactional
    @Override
    public void newCustBind(String entId, String custName, SexEnum sex, String custPhone, String openId, String defunctId) {
        List<String> ids = appTenantService.queryTenantIdByEntId(entId);
        if (ids.size() <= 0) {
            return;
        }

        LambdaQueryWrapper<Defunct> query = Wrappers.lambdaQuery();
        query.eq(Defunct::getId, defunctId);
        Defunct defunct = baseMapper.selectNotTenantById(defunctId);
        if (defunct == null) {
            throw new BusinessEntityNotFoundException(defunctId, "逝者信息");
        }

        // 用户有没有，没有则创建
        User user = userService.createOpenIdUser(openId, defunct.getTenantId());

        //客户有没有，没有则创建
        LambdaQueryWrapper<Customer> queryByCustomer = Wrappers.lambdaQuery();
        queryByCustomer.eq(Customer::getPhone, custPhone);
        queryByCustomer.eq(Customer::getUserId, user.getId());
        Customer customer = customerMapper.selectOne(queryByCustomer);
        if (customer == null) {
            customer = new Customer();
            customer.setName(custName);
            customer.setSex(sex.getValue());
            customer.setPhone(custPhone);
            customer.setIsDelete(false);
            customer.setUserId(user.getId());
            customer.setTenantId(defunct.getTenantId());
            customer.setCreateAt(user.getId());
            customer.insert();
        }

        //与逝者是否有绑定
        LambdaQueryWrapper<CustomerDefunct> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(CustomerDefunct::getCustomerId, customer.getId());
        queryWrapper.eq(CustomerDefunct::getDefunctId, defunctId);
        CustomerDefunct customerDefunct = customerDefunctMapper.selectOne(queryWrapper);
        if (customerDefunct == null) {
            customerDefunct = new CustomerDefunct();
        }
        customerDefunct.setCustomerId(customer.getId());
        customerDefunct.setDefunctId(defunct.getId());
        customerDefunct.setCreateAt(user.getId());
        customerDefunct.insertOrUpdate();
    }

    @Override
    public void bind(String custId, String defunctId) {
        LambdaQueryWrapper<CustomerDefunct> lq = Wrappers.lambdaQuery();
        lq.eq(CustomerDefunct::getCustomerId, custId);
        lq.eq(CustomerDefunct::getDefunctId, defunctId);
        if (customerDefunctMapper.selectCount(lq) <= 0) {
            CustomerDefunct obj = new CustomerDefunct();
            obj.setCustomerId(custId);
            obj.setDefunctId(defunctId);
            obj.insert();
        }
    }

    @Override
    public void updateBirthdayNotify(String id) {
        Defunct obj = baseMapper.selectById(id);
        if(obj==null){
            return;
        }

        obj.setBirthdayNotify(new Date());
        obj.updateById();
    }

    @Override
    public void updateDefunctDateNotify(String id) {
        Defunct obj = baseMapper.selectById(id);
        if(obj==null){
            return;
        }

        obj.setDefunctDateNotify(new Date());
        obj.updateById();
    }

    @Override
    public List<DefunctExt> queryByUserId(String userId) {
        List<String> ids = queryDefunctIdByUserId(userId);
        if (StringUtils.isNullOrEmpty(ids)) {
            return new ArrayList<>();
        }
        return defunctExtMapper.selectBatchIds(ids);
    }

    @Override
    public List<DefunctExt> queryByCustId(String custId) {
        LambdaQueryWrapper<CustomerDefunct> lq = Wrappers.lambdaQuery();
        lq.eq(CustomerDefunct::getCustomerId, custId);
        List<String> ids = customerDefunctMapper.selectList(lq).stream().map(s -> s.getDefunctId()).distinct().collect(Collectors.toList());
        if (StringUtils.isNullOrEmpty(ids)) {
            return new ArrayList<>();
        }
        return defunctExtMapper.selectBatchIds(ids);
    }

    @Override
    public List<String> queryDefunctIdByUserId(String userId) {
        LambdaQueryWrapper<Customer> lq = Wrappers.lambdaQuery();
        lq.eq(Customer::getUserId, userId);
        lq.eq(Customer::getTenantId, SecurityUtils.getUserContent().getTenantId());
        List<String> ids = customerMapper.selectList(lq).stream().map(s -> s.getId()).collect(Collectors.toList());

        if (ids.size() <= 0) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<CustomerDefunct> query = Wrappers.lambdaQuery();
        query.in(CustomerDefunct::getCustomerId, ids);
        List<String> result = customerDefunctMapper.selectList(query).stream().map(s -> s.getDefunctId()).distinct().collect(Collectors.toList());
        return result;
    }

    @Override
    public List<DefunctExt> queryByTombSkuId(String id) {
        LambdaQueryWrapper<DefunctExt> lq = Wrappers.lambdaQuery();
        lq.eq(DefunctExt::getTombSkuId, id);
        lq.eq(DefunctExt::getIsDelete, false);
        return defunctExtMapper.selectList(lq);
    }
}